
#include <iostream>
#include <stdio.h>
#include <string>
#include "Shell.h"
#include "Worker.h"
#include "Message_System.h"
#include "Message_Kill_Revive.h"

using namespace std;


Shell::Shell() {
	_inbox	= new Mailbox(SHELL_MAILBOX_SIZE);
	_mailer = new Mailer(_inbox);
}

Shell::~Shell() {
	delete(_inbox);
	delete(_mailer);
}

bool Shell::is_node_exists(int id)
{
	return id >= 1  &&  id <= _mailer->getGraph()->getNumber_of_nodes();
}
void Shell::show_menu()
{
	char choice;
	string filename;
	string textMessage;
	int unique_id;

	print_command_list();
	cin >> choice;

	while (choice != '8')
	{
		switch (choice)
		{
			case '1':
				cout << "Enter net's file name: ";
				cin >> filename;
				//filename = "net1.txt";
				_filename = filename;
				cout << endl << endl;
				create_net(filename);
				break;

			case '2':
				unique_id = 0;
				cout << "Enter node's id to kill: ";
				cin >> unique_id;
				cout << endl;
				kill_node(unique_id);
				break;


			case '3':
				unique_id = 0;
				cout << "Enter node's id to revive: ";
				cin >> unique_id;
				cout << endl;
				revive_node(unique_id);
				break;


			case '4':
				kill_all();
				break;


			case '5':
				int worker_id;
				cout << "Enter Worker Number.: ";
				cin >> worker_id;
				cout << endl;
				printRT(worker_id);
				break;


			case '6':{

				int source,target;
				cout << "Enter source: ";
				cin >> source;
				cout << endl;
				cout << "Enter target: ";
				cin >> target;
				cout << endl;
				cout << "Enter message to send: ";
				cin >> textMessage;
				cout << endl << endl;
				Message_System* msg = new Message_System(SHELL, source, target, target, textMessage);
				send_packet(msg);

			}
				break;


			case '7':
				int algo;
				cout << "Enter algorithm:" << endl;
				cout << "----------------" << endl;
				cout << "1. Round Robin" << endl;
				cout << "2. Multilevel algorithm" << endl;
				cout << "3. Our algorithm" << endl;
				cout << endl << "Your choice: ";
				cin >> algo;
				cout << endl << endl;
				run(algo);
				break;


			case '8':
				// nothing to do
				break;


			default:
				cout << "Wrong command" << endl << endl;
				break;
		}
		sleep(2);
		print_command_list();
		cin >> choice;
	}
}

void Shell::print_command_list()
{
	cout << "\nChoose command:" << endl;
	cout << "===============" << endl;
	cout << "1. create_net" << endl;
	cout << "2. kill_node" << endl;
	cout << "3. revive_node" << endl;
	cout << "4. kill_all" << endl;
	cout << "5. printRT" << endl;
	cout << "6. send_packet" << endl;
	cout << "7. run" << endl;
	cout << "8. exit" << endl;
	cout << endl;
	cout << "Your choice: ";
}

// 1
void Shell::create_net(string filename)
{
	bool is_created = _mailer->creat_net(filename);
	if ( is_created )
	{
		cout << "Net created." << endl << endl;
	}
	else
	{
		cout << "Net NOT created." << endl << endl;
	}
}


// 2
void Shell::kill_node(int unique_id)
{
	if ( !is_node_exists(unique_id) )
	{
		cout << "No such node." << endl;
	}
	else
	{
		_mailer->getGraph()->getNodes()->at(unique_id)->setActive(false);
		for (int i = 1; i < getMailer()->getGraph()->getNumber_of_nodes()+1; ++i) {
			Message_Kill_Revive* message = new Message_Kill_Revive(SHELL, SHELL, i, i, KILL, unique_id);
			getMailer()->put_in_inbox(message);
		}
	}
}

// 3
void Shell::revive_node(int unique_id)
{
	if ( !is_node_exists(unique_id) )
	{
		cout << "No such node." << endl;
	}
	else
	{
		((Worker*)_mailer->getGraph()->getNodes()->at(unique_id))->setIs_alive(true);
		((Worker*)_mailer->getGraph()->getNodes()->at(unique_id))->setActive(true);
		for (int i = 1; i < getMailer()->getGraph()->getNumber_of_nodes()+1; ++i) {
			Message_Kill_Revive* message = new Message_Kill_Revive(SHELL, SHELL, i, i, REVIVE, unique_id);
			getMailer()->put_in_inbox(message);
		}
	}
}

// 4
void Shell::kill_all()
{
	for (int i = 1; i < _mailer->getGraph()->getNumber_of_nodes()+1; ++i) {
		_mailer->put_in_inbox(new Message_System(SHELL, i, i, i, "die"));
	}
	sleep(3);
	_mailer->put_in_inbox(new Message_System(SHELL, MAILER, MAILER, MAILER,"die"));
	sleep(3);
	create_net(_filename);
}

// 5
void Shell::printRT(int unique_id)
{
	if ( !is_node_exists(unique_id) )
	{
		cout << "No such node." << endl;
	}
	else
	{
		cout << "\nRoutering Table of Worker " << unique_id << ":" << endl;
		cout << "-----------------------------" << endl;
		((Worker*)_mailer->getGraph()->getNodes()->at(unique_id))->getRoutering_table()->print();
	}
}

// 6
void Shell::send_packet(Message* msg)
{
	cout << "sending packet..." << endl;
	_mailer->put_in_inbox(msg);
}

// 7
void Shell::run(int schedule_num)
{
	// send a msg to mailer requesting it to start simulation with
	// scheduling algorithm <schedule_num>:
	this->_mailer->start(schedule_num);
//	pthread_t thread_id;
//	if ( pthread_create(&thread_id, NULL, run1, NULL) != 0 )
//	{
//		perror("OSThread thread creation failed");
//		//exit(1);
//	}
}

//Message Shell::makeMessage(source, target, textMessage){
//	Message* msg = new Message(source, target, textMessage);
//}
